package com.douqu.game.battle.entity.tmp;

import com.douqu.game.battle.controller.BattleController;
import com.douqu.game.battle.controller.sprite.MonsterController;
import com.douqu.game.battle.controller.sprite.PlayerController;
import com.douqu.game.battle.controller.sprite.SpriteController;
import com.douqu.game.battle.entity.BattleSkill;
import com.douqu.game.battle.entity.aobject.BattleAObject;
import com.douqu.game.battle.entity.aobject.BattleMasterAObject;
import com.douqu.game.battle.entity.aobject.BattleSoldierAObject;
import com.douqu.game.battle.server.GameServer;
import com.douqu.game.battle.util.BattleUtils;
import com.douqu.game.core.config.StableDataConfig;
import com.douqu.game.core.config.battle.MonsterConfig;
import com.douqu.game.core.config.card.CardConfig;
import com.douqu.game.core.config.challenge.CardParamConfig;
import com.douqu.game.core.config.challenge.ExpeditionConfig;
import com.douqu.game.core.config.challenge.WorldBossConfig;
import com.douqu.game.core.config.challenge.WorldBossParameterConfig;
import com.douqu.game.core.config.common.CommonData;
import com.douqu.game.core.config.common.GoodsData;
import com.douqu.game.core.config.common.Position;
import com.douqu.game.core.config.map.CityArmyGroupConfig;
import com.douqu.game.core.config.sprite.MasterConfig;
import com.douqu.game.core.config.sprite.MasterParamConfig;
import com.douqu.game.core.e.E_BattleAObjectStatus;
import com.douqu.game.core.e.E_StableDataType;
import com.douqu.game.core.entity.activity.RankCamp;
import com.douqu.game.core.entity.battle.*;
import com.douqu.game.core.entity.db.CardDB;
import com.douqu.game.core.entity.ext.BagInfo;
import com.douqu.game.core.entity.ext.data.challenge.CampBattleData;
import com.douqu.game.core.factory.ConstantFactory;
import com.douqu.game.core.factory.DataFactory;
import com.douqu.game.core.protobuf.SGCommonProto;
import com.douqu.game.core.protobuf.SGMainProto;
import com.douqu.game.core.protobuf.SGWarProto;
import com.douqu.game.core.util.LogUtils;

import java.io.Serializable;
import java.rmi.RemoteException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * 精灵战斗数据类
 * Created by bean on 2017/7/25.
 */
public class SpriteBattleTmp implements Serializable {

    protected static final long serialVersionUID = 1L;


    protected BattleController battleController;

    protected SpriteController spriteController;

    /**
     * 对手
     */
    protected SpriteBattleTmp targetBattleTmp;

    /**
     * 上一次出兵路线
     */
    protected int lastSoldierRoute;
    /**
     * 卡牌列表
     */
    protected List<CardDB> cardList;

    protected Map<Integer, CardDB> cardMap;

    /**
     * 历史卡牌
     */
    protected List<CardDB> historyCards;

    /**
     * 队伍编号
     */
    protected int teamNo;

    /**
     * 主将
     */
    public BattleAObject masterSoldier;

    /**
     * 召唤出来的兵
     */
    protected List<BattleAObject> soldierList;

    protected List<BattleAObject> historySoldiers;

    /**
     * 上一场已经死亡的兵,要发给前端展示
     */
    protected List<SpriteTemp> historyDeadSoldiers;

    /**
     * 准备
     */
    protected boolean ready;


    /**
     * 当前水晶值
     */
    protected int curCrystal;

    /**
     * 最大水晶值
     */
    protected int maxCrystal;

    /**
     * 水晶成长
     * key: 战斗运行时间
     */
    protected Map<Integer, CrystalGrow> crystalGrowMap;

    /**
     * 是否是自动
     */
    protected boolean isAuto;

//    /**
//     * 公共CD
//     */
//    protected long nextUserSkillTime;

    /**
     * 出卡的公共CD
     */
    protected long nextPutCardTime;

    /**
     * 杀死敌人数量
     */
    public int killCount;

    /**
     * 上一场的历史数据
     */
    protected BattleTemp battleTemp;

    protected int lv;


    public void init(BattleController battleController, SpriteController spriteController, int teamNo)
    {
        StableDataConfig stableDataConfig = DataFactory.getInstance().getGameObject(DataFactory.STABLE_DATA_KEY, E_StableDataType.CUR_CRYSTAL.getCode());
        if (stableDataConfig == null){
            LogUtils.error("StableDataConfig error ->" + "no have type " + E_StableDataType.CUR_CRYSTAL.getMsg());
            return;
        }
        this.curCrystal = stableDataConfig.intArray[0];
        this.maxCrystal = stableDataConfig.intArray[1];
        int start = 0;
        crystalGrowMap = new ConcurrentHashMap<>();

        CommonData[] crystalGrowAry = null;
        if(BattleUtils.TEST_BATTLE && teamNo == ConstantFactory.BATTLE_TEAM_2)
        {
            crystalGrowAry = BattleUtils.TEAM2_CRYSTAL_GROW;
        }
        else
        {
            if(teamNo == ConstantFactory.BATTLE_TEAM_2)
            {
                if(battleController.getBattleType() == SGCommonProto.E_BATTLE_TYPE.BATTLE_TYPE_EXPEDITION)
                {
                    ExpeditionConfig expeditionConfig = DataFactory.getInstance().getGameObject(DataFactory.EXPEDITION_KEY, Integer.parseInt(battleController.getTargetData()));
                    crystalGrowAry = expeditionConfig.crystalGrow;
                }
                else if(battleController.getBattleType() == SGCommonProto.E_BATTLE_TYPE.BATTLE_TYPE_WORLD_BOSS)
                {
                    WorldBossConfig worldBossConfig = DataFactory.getInstance().getGameObject(DataFactory.WORLD_BOSS_KEY, Integer.parseInt(battleController.getTargetData()));
                    crystalGrowAry = worldBossConfig.crystalGrow;
                }
            }

            if(crystalGrowAry == null)
            {
                stableDataConfig = DataFactory.getInstance().getGameObject(DataFactory.STABLE_DATA_KEY, E_StableDataType.CRYSTAL_GROW.getCode());
                if (stableDataConfig == null){
                    LogUtils.error("StableDataConfig error ->" + "no have type " + E_StableDataType.CRYSTAL_GROW.getMsg());
                    return;
                }
                crystalGrowAry = stableDataConfig.commons;
            }
        }

        for(CommonData data : crystalGrowAry)
        {
            for(int i = start + data.value; i <= data.id; i+=data.value)
            {
                crystalGrowMap.put(i, new CrystalGrow());
            }

            start = data.id;
        }

        MasterConfig masterConfig = null;
        this.lv = 1;
        Position masterPosition = null;
        try {
            if(spriteController instanceof PlayerController)
            {
                masterConfig = DataFactory.getInstance().getGameObject(DataFactory.MASTER_KEY, ((PlayerController) spriteController).getPlayer().master);
                if(masterConfig == null)
                    masterConfig = (MasterConfig) DataFactory.getInstance().getDataList(DataFactory.MASTER_KEY).get(0);

                lv = ((PlayerController) spriteController).getPlayer().getLv();
                masterPosition = battleController.getMasterPos(teamNo, masterConfig.gridArea);
                String masterPlayerIndex = "";
                if(battleController.getInitParam() instanceof BattleInitParamWorldMap)
                    masterPlayerIndex = ((BattleInitParamWorldMap) battleController.getInitParam()).getMasterPlayerIndex();
                battleTemp = GameServer.getInstance().getIMainServer().getBattleTemp(battleController.getBattleType().getNumber(), spriteController.getObjectIndex(), masterPlayerIndex);
            }
            else if(spriteController instanceof MonsterController)
            {
                masterConfig = ((MonsterController) spriteController).getMasterConfig();
                masterPosition = battleController.getMasterPos(teamNo, ((MonsterController) spriteController).getMasterConfig().gridArea);
                if(battleController.getBattleType() == SGCommonProto.E_BATTLE_TYPE.BATTLE_TYPE_WORLD_BOSS)
                {
                    battleTemp = GameServer.getInstance().getIMainServer().getBattleTemp(battleController.getBattleType().getNumber(), null);
                    if(battleTemp != null)
                    {
                        lv = battleTemp.getStar();
                    }
                }
                else
                {
                    if(battleController.getBattleType() == SGCommonProto.E_BATTLE_TYPE.BATTLE_TYPE_WORLD_MAP)
                    {
                        battleTemp = GameServer.getInstance().getIMainServer().getBattleTemp(battleController.getBattleType().getNumber(), spriteController.getObjectIndex());
                        String[] params = battleController.getTargetData().split(ConstantFactory.UNDERLINE);
                        CityArmyGroupConfig cityArmyGroupConfig = DataFactory.getInstance().getGameObject(DataFactory.CITY_ARMY_GROUP_KEY, Integer.parseInt(params[1]));
                        lv = cityArmyGroupConfig.getLv();
                    }
                    else
                    {
                        MasterParamConfig masterParamConfig = ((MonsterController) spriteController).getBattleInitConfig().getMasterParam();
                        if(masterParamConfig != null)
                        {
                            lv = masterParamConfig.level;
                        }
                        else
                        {
                            LogUtils.error("主将配置MasterParam错误 -> " + ((MonsterController) spriteController).getBattleInitConfig().getName());
                        }
                    }
                }

                ((MonsterController) spriteController).setMasterLv(lv);
            }
        } catch (RemoteException e) {
            e.printStackTrace();
        }

        this.masterSoldier = new BattleMasterAObject(spriteController, masterConfig, battleController.createCardUniqueId+teamNo, lv, teamNo, masterPosition, battleTemp);
        this.battleController = battleController;
        this.spriteController = spriteController;
        this.teamNo = teamNo;
        this.soldierList = new CopyOnWriteArrayList<>();
        this.historySoldiers = new CopyOnWriteArrayList<>();
        this.cardList = new CopyOnWriteArrayList<>();
        this.historyCards = new CopyOnWriteArrayList<>();
        this.historyDeadSoldiers = new CopyOnWriteArrayList<>();
        this.cardMap = new ConcurrentHashMap<>();

        CardDB supportCard = null;

        if(spriteController instanceof PlayerController)
        {
            PlayerController playerController = (PlayerController) spriteController;

            BagInfo bagInfo = playerController.getPlayer().getExtInfo(BagInfo.class);

            List<CardDB> list = null;
            if(battleController.getBattleType() == SGCommonProto.E_BATTLE_TYPE.BATTLE_TYPE_SPAN_CAMP)
                list = playerController.getPlayer().getCampCardList();
            else if(battleController.getBattleType() == SGCommonProto.E_BATTLE_TYPE.BATTLE_TYPE_WORLD_MAP)
                list = playerController.getPlayer().getWorldMapCardList();
            else
                list = bagInfo.getCardData().getBattleCardList();

            LogUtils.info("teamNo -> " + teamNo + " name -> " + playerController.getName() + " battleTemp -> " + battleTemp);
            LogUtils.debug("list -> " + list);
            if(battleTemp == null)
            {
                cardList.addAll(list);
                historyCards.addAll(list);

                if(spriteController.getSupportCardId() != 0 && spriteController.getSupportCardParamId() != 0)
                {
                    CardConfig cardConfig = DataFactory.getInstance().getGameObject(DataFactory.CARD_KEY, spriteController.getSupportCardId());
                    if(cardConfig != null)
                    {
                        supportCard = new CardDB(cardConfig.id);
                        supportCard.setSupportParamId(spriteController.getSupportCardParamId());

                        CardParamConfig cardParamConfig = DataFactory.getInstance().getGameObject(DataFactory.CARD_PARAM_KEY, spriteController.getSupportCardParamId());
                        if(cardParamConfig != null)
                        {
                            supportCard.setMonsterData(cardParamConfig.cardParams);
                            supportCard.setExtAttr(cardParamConfig.paraments);
                        }
                        else
                        {
                            LogUtils.error("支援卡参数ID错误 -> " + spriteController.getSupportCardParamId());
                        }

                        LogUtils.info("支援卡上场 -> " + cardConfig.getId() + " -> " + spriteController.getSupportCardParamId());
                    }
                }
            }
            else
            {
                SpriteTemp spriteSoldierTemp = null;
                CardDB historyCard = null;
                for(CardDB cardDB : list)
                {
                    spriteSoldierTemp = getSoldierHistoryTemp(cardDB.id, SpriteTemp.IGNORE_INDEX);
                    if(spriteSoldierTemp != null)
                    {
                        if(spriteSoldierTemp.getHp() > 0)
                        {
                            LogUtils.info("卡 -> " + cardDB.getConfig().name + " HP -> " + spriteSoldierTemp.getHp() + "/" + spriteSoldierTemp.getMaxHp());
                            historyCard = new CardDB(cardDB);
                            cardList.add(historyCard);
                            historyCards.add(historyCard);
                        }
                        else
                        {
                            LogUtils.info("卡 -> " + cardDB.id + "-"+ cardDB.getConfig().name + " 已经在上一场战斗中死亡");
                            spriteSoldierTemp.setCacheMaxHp(0);
                            historyDeadSoldiers.add(spriteSoldierTemp);
                        }
                    }
                    else
                    {
                        LogUtils.info("卡不存在 -> " + cardDB.id);
                    }
                }
            }

            if(battleController.getBattleDetailType().isPlayerBattle())
                isAuto = playerController.isOnlinePlayer() ? playerController.isAutoBattle() : true;
            else
                isAuto = true;
        }
        else if(spriteController instanceof MonsterController)
        {
            MonsterController monsterController = (MonsterController) spriteController;
            int[] monsterLv = null;
            CommonData[] extAttr = null;
            if(battleController.getBattleType() == SGCommonProto.E_BATTLE_TYPE.BATTLE_TYPE_WORLD_BOSS)
            {
                WorldBossParameterConfig worldBossParameterConfig = DataFactory.getInstance().getGameObject(DataFactory.WORLD_BOSS_PARAM_KEY, lv);
                if(worldBossParameterConfig == null)
                    worldBossParameterConfig = (WorldBossParameterConfig) DataFactory.getInstance().getDataList(DataFactory.WORLD_BOSS_PARAM_KEY).get(0);
                monsterLv = worldBossParameterConfig.monsterLv;
            }
            else
            {
                monsterLv = monsterController.getMonsterLv();
                extAttr = monsterController.getExtAttr();
            }
            MonsterConfig monsterConfig = monsterController.getMonsterConfig();
            if(monsterConfig != null)
            {
                CardDB cardDB = null;
                SpriteTemp spriteSoldierTemp = null;
                int index = 0;
                int[] cardParam;
                int cardParamId ;
                CardConfig cardConfig;
                boolean isNullCardParam = monsterConfig.isNullCardParam();
                if(battleTemp != null)
                {
                    for (int i = 0; i <  monsterConfig.cards.length; i++) {
                        cardConfig = monsterConfig.cards[i];
                        spriteSoldierTemp = getSoldierHistoryTemp(cardConfig.id, index);
                        if(spriteSoldierTemp != null)
                        {
                            if(spriteSoldierTemp.getHp() > 0)
                            {
                                LogUtils.info("卡 -> " + cardConfig.name + " HP -> " + spriteSoldierTemp.getHp() + "/" + spriteSoldierTemp.getMaxHp());
                                cardDB = new CardDB(cardConfig.id);
                                if (!isNullCardParam)
                                {
                                    cardParamId = monsterConfig.cardParam[i];
                                    CardParamConfig cardParamConfig = DataFactory.getInstance().getGameObject(DataFactory.CARD_PARAM_KEY, cardParamId);
                                    cardDB.setMonsterData(cardParamConfig.cardParams);
                                    cardDB.setExtAttr(cardParamConfig.paraments);
                                }
                                else
                                {
                                    cardDB.setMonsterData(monsterLv);
                                    cardDB.setExtAttr(extAttr);
                                }

                                cardDB.setIndex(index);
                                cardList.add(cardDB);
                                historyCards.add(cardDB);
                            }
                            else
                            {
                                LogUtils.info("卡 -> " + cardConfig.id + "-" + cardConfig.name + " 已经在上一场战斗中死亡");
                                spriteSoldierTemp.setCacheMaxHp(0);
                                historyDeadSoldiers.add(spriteSoldierTemp);
                            }
                        }
                        index++;
                    }
                }
                else
                {
                    // 统一
                    for (int i = 0; i <  monsterConfig.cards.length; i++){
                        cardConfig =monsterConfig.cards[i];
                        cardDB = new CardDB(BattleUtils.TEST_BATTLE&&BattleUtils.TEAM2_CARD!=0 ? BattleUtils.TEAM2_CARD : cardConfig.id);
                        if (!isNullCardParam)
                        {
                            cardParamId = monsterConfig.cardParam[i];
                            CardParamConfig cardParamConfig = DataFactory.getInstance().getGameObject(DataFactory.CARD_PARAM_KEY, cardParamId);
                            cardDB.setMonsterData(cardParamConfig.cardParams);
                            cardDB.setExtAttr(cardParamConfig.paraments);
                        }
                        else {
                            cardParam = monsterLv;
                            cardDB.setMonsterData(cardParam);
                            cardDB.setExtAttr(extAttr);
                        }
                        cardDB.setIndex(index++);
                        cardList.add(cardDB);
                        historyCards.add(cardDB);
                    }
                }
            }
            else
            {
                LogUtils.error("monsterConfig is null -> " + battleController.getBattleDetailType());
            }


            isAuto = true;
        }

        //TODO 后期记得优化,因为打NPC的时候对方是有可能有重复卡的
        for(CardDB card : cardList)
        {
            cardMap.put(card.id, card);
        }

        //打乱顺序
        if(!battleController.isFirstLevel() || spriteController instanceof MonsterController)
            Collections.shuffle(cardList);

            if(supportCard != null)
            {
            cardList.add(0, supportCard);
            cardMap.put(supportCard.id, supportCard);
        }

        nextPutCardTime = DataFactory.currentTime + BattleController.PUT_CARD_CD_TIME;
    }


    public void updateCrystal(final int battleTime)
    {
        if(!isMaxCrystal())
        {
//            LogUtils.debug(spriteController.getName() + " 计算水晶成长，当前战斗运行时间:" + battleTime);
            if(crystalGrowMap.get(battleTime) != null)
            {
                if(!crystalGrowMap.get(battleTime).added)
                {
                    curCrystal++;
                }
                crystalGrowMap.remove(battleTime);
            }
//            LogUtils.debug("当前水晶："+curCrystal);
        }

        masterSoldier.checkAISkill(battleTime);
    }

    /**
     *
     * @param currentTime 当前时间
     */
    public void update(long currentTime)
    {
        if(battleController.isEnd())
        {
            LogUtils.debug("战斗已经结束 -> " + battleController);
            return;
        }

        if(isAuto)
        {
            if(battleController.isEnd())
            {
                LogUtils.debug("战斗已经结束 -> " + battleController);
                return;
            }
            //出牌AI
            checkAI(currentTime);
        }

        if(battleController.isEnd())
        {
            LogUtils.debug("战斗已经结束 -> " + battleController);
            return;
        }

        //检测主将攻击
        masterSoldier.checkDefaultSkillTarget(currentTime);

        if(battleController.isEnd())
        {
            LogUtils.debug("战斗已经结束 -> " + battleController);
            return;
        }

        masterSoldier.update(currentTime);

        if(battleController.isEnd())
        {
            LogUtils.debug("战斗已经结束 -> " + battleController);
            return;
        }

        //小兵前进
        for(BattleAObject aObject : soldierList)
        {
            if(aObject.isDie())
                continue;

//                LogUtils.error("soldier:" + aObject);
            if(aObject.getStatus() == E_BattleAObjectStatus.GOING)
            {
//                    LogUtils.error(aObject.getTeamNo() + "  " + aObject.getUniqueId() + "  向前走");
                aObject.go();
            }
        }

//        if(battleController.isEnd())
//            return;

        //检测小兵攻击
        for(BattleAObject soldier : soldierList)
        {
//            LogUtils.debug("检测更新1 -> " + soldier);
            if(soldier.isDie())
                continue;
//            LogUtils.debug("检测更新2 -> " + soldier);
            if(soldier.checkDefaultSkillTarget(currentTime))
            {
//                LogUtils.debug("检测更新3 -> " + soldier);
                if(battleController.isEnd())
                {
                    LogUtils.debug("战斗已经结束 -> " + battleController);
                    return;
                }
            }
            else
            {
                soldier.checkFindRoute();
            }

            soldier.update(currentTime);
            if(battleController.isEnd())
            {
                LogUtils.debug("战斗已经结束 -> " + battleController);
                return;
            }
        }



    }


    public void addCrystal(int value)
    {
        curCrystal += value;
        curCrystal = curCrystal < 0 ? 0 : curCrystal;
        curCrystal = curCrystal > maxCrystal ? maxCrystal : curCrystal;
    }



    public boolean checkAI(long currentTime)
    {
        if(!isAuto)
        {
            LogUtils.debug("你是玩家你不是AI!");
            return false;
        }

        if(BattleUtils.TEST_BATTLE)
        {
            if(teamNo == ConstantFactory.BATTLE_TEAM_2 && soldierList.size() >= BattleUtils.ONLY_ENEMY)
            {
                // 测试时只出一个兵
                return false;
            }
        }

        BattleSkill skill = masterSoldier.getReleaseSkill(currentTime);
        //技能是否可以释放
        if(skill != null && skill.checkCrystal(curCrystal))
        {
            skill.release();
        }

//        LogUtils.warn(teamNo + " 当前时间 -> " + currentTime + " nextPutCardTime -> " + nextPutCardTime + " size -> " + cardList.size());
        int cardCount = cardList.size();
        if(curCrystal > 0 && currentTime + 10 >= nextPutCardTime && cardCount > 0)
        {
            //对手场上的兵
//            List<BattleAObject> targetSoldierList = targetBattleTmp.getSoldierList();
            CardDB result = null;
            int route = 0;
            //在这个列表里选择要出的卡
            List<CardDB> putCardList = cardList.subList(0, cardCount > BattleController.PUT_CARD_COUNT ? BattleController.PUT_CARD_COUNT : cardCount);

            //首先出支援卡
            for(CardDB cardDB : putCardList)
            {
                if(cardDB.getSupportParamId() != 0)
                {
                    result = cardDB;
                    break;
                }
            }
            if(result == null)
            {
                //20180324修改出兵路线规则，上下轮流出,出最高战力的兵
                if(!battleController.isFirstLevel())//不是第一个副本关卡才排序
                {
                    putCardList.sort(new Comparator<CardDB>() {
                        @Override
                        public int compare(CardDB o1, CardDB o2) {
                            return new Integer(o2.fc).compareTo(o1.fc);
                        }
                    });
                }
                result = putCardList.get(0);
            }
            route = lastSoldierRoute == ConstantFactory.ROUTE_TOP ? ConstantFactory.ROUTE_BOTTOM : ConstantFactory.ROUTE_TOP;
            //以下是原来的规则
//            if(targetSoldierList.size() > 0)
//            {
//                Map<Integer, List<CardDB>> qualityCards = new ConcurrentHashMap<>();
//                CardConfig cardConfig = null;
//                List<CardDB> cardTempList = null;
//                int maxQuality = 0;
//                for(CardDB cardDB : putCardList)
//                {
//                    cardConfig = cardDB.getConfig();
//                    cardTempList= qualityCards.get(cardConfig.quality);
//                    if(cardTempList == null)
//                    {
//                        cardTempList = new CopyOnWriteArrayList<>();
//                        qualityCards.put(cardConfig.quality, cardTempList);
//                        maxQuality = maxQuality < cardConfig.quality ? cardConfig.quality : maxQuality;
//                    }
//                    cardTempList.add(cardDB);
//                }
//
//                /******************************************
//                 * 品质最高的,克制对方场上的兵 -> 跟对方场上兵相同属性 -> 被对方场上的兵克制
//                 */
//                cardTempList = qualityCards.get(maxQuality);
//                //克制对方场上的兵
//                choose1:for(CardDB cardDB : cardTempList)
//                {
//                    for(BattleAObject soldier : targetSoldierList)
//                    {
//                        if(cardDB.getConfig().getSoldier().isRestrict(soldier.getSprite()))
//                        {
//                            LogUtils.debug("克制对方出兵");
//                            result = cardDB;
//                            break choose1;
//                        }
//                    }
//                }
//                if(result == null)
//                {
//                    //跟对方场上兵相同属性
//                    choose2:for(CardDB cardDB : cardTempList)
//                    {
//                        for(BattleAObject soldier : targetSoldierList)
//                        {
//                            if(cardDB.getConfig().getSoldier().isSameRestrict(soldier.getSprite()))
//                            {
//                                LogUtils.debug("克制一样出兵");
//                                result = cardDB;
//                                break choose2;
//                            }
//                        }
//                    }
//                }
//
//                if(result == null)
//                {
//                    //被对方场上的兵克制
//                    choose3:for(CardDB cardDB : cardTempList)
//                    {
//                        for(BattleAObject soldier : targetSoldierList)
//                        {
//                            if(soldier.getSprite().isRestrict(cardDB.getConfig().getSoldier()))
//                            {
//                                LogUtils.debug("被对方克制出兵");
//                                result = cardDB;
//                                break choose3;
//                            }
//                        }
//                    }
//                }
//
//                //两路路线上,对方的兵数-我方的兵数,取小的那和边放
//                //我方最高品质里检测对对方的兵的克制关系,若有则出该卡,有多个情况则随机
//                if(result != null)
//                {
//                    int topCount = targetBattleTmp.getRouteSoldierCount(ConstantFactory.ROUTE_TOP) - getRouteSoldierCount(ConstantFactory.ROUTE_TOP);
//                    int botCount = targetBattleTmp.getRouteSoldierCount(ConstantFactory.ROUTE_BOTTOM) - getRouteSoldierCount(ConstantFactory.ROUTE_BOTTOM);
//                    route = topCount < botCount ? ConstantFactory.ROUTE_BOTTOM : ConstantFactory.ROUTE_TOP;
//                    LogUtils.debug("出兵的路线 -> topCount:" + topCount + " botCount:" + botCount + " route:" + route);
//                }
//            }
//            else
//            {
//                //我方出最高品质高最等级的卡,相同则随机,路线随机(上下两条路)
//                CardDB maxQualityCard = Utils.getMaxGameObject(putCardList, new Comparator<CardDB>() {
//                    @Override
//                    public int compare(CardDB o1, CardDB o2) {
//                        return new Integer(o1.getConfig().quality).compareTo(o2.getConfig().quality);
//                    }
//                });
//                List<CardDB> tempList = new CopyOnWriteArrayList<>();
//                for(CardDB cardDB : putCardList)
//                {
//                    if(cardDB.getLv() == maxQualityCard.getLv())
//                    {
//                        tempList.add(cardDB);
//                    }
//                }
//                result = tempList.get((int) (Math.random() * tempList.size()));
//
//                if(result != null)
//                {
//                    route = com.bean.core.util.Utils.getRandom(2) == 1 ? ConstantFactory.ROUTE_TOP : ConstantFactory.ROUTE_BOTTOM;
//                }
//            }

            if(result != null)
            {
                LogUtils.debug("AI出兵结果:" + result);
                soldierBorn(result, route);
                return true;
            }
        }

        return false;
    }


    public void soldierBorn(CardDB cardDB, int route)
    {
        List<Position> posList = new ArrayList<>();
        CardConfig cardConfig = cardDB.getConfig();
        for(int i = 0; i < cardConfig.soldierCount; i++)
        {
            posList.add(BattleUtils.getSoldierBornPos(battleController.getAstar().getAstarMap(), teamNo, cardConfig.getSoldier().initRange, route, cardConfig.getSoldier().gridArea));
        }

        soldierBorn(cardDB, posList);

        lastSoldierRoute = route;
    }
    /**
     * 小兵出生
     */
    public void soldierBorn(CardDB cardDB, List<Position> posList)
    {
        CardConfig cardConfig = cardDB.getConfig();
        if(posList != null && posList.size() < cardConfig.soldierCount)
            return;

        addCrystal(-cardConfig.crystal);
        toBattlefield(cardDB);

        BattleAObject battleSoldierAObject = null;

        //转发消息
        SGWarProto.S2C_ToBattle.Builder response = SGWarProto.S2C_ToBattle.newBuilder();
        String objectIndex = getSpriteObjectIndex();
        if(objectIndex != null)
            response.setPlayerIndex(objectIndex);

        SGCommonProto.Card.Builder card = SGCommonProto.Card.newBuilder();
        card.setId(cardDB.id);
        card.setLv(cardDB.getLv());
        card.setStar(cardDB.star);
        card.setFc(cardDB.fc);
        response.setCard(card);

        response.setIsCardSoldier(true);

        List<BattleAObject> sendList = new CopyOnWriteArrayList<>();

        LogUtils.info("出战 -> 队伍:" + teamNo + "  card -> id:" + cardDB.id + ",index:" + cardDB.getIndex());

        SpriteTemp spriteTemp = getSoldierHistoryTemp(cardDB.id, cardDB.getIndex());

        for(int i = 0; i < cardConfig.soldierCount; i++)
        {
            battleSoldierAObject = new BattleSoldierAObject(spriteController, cardDB,
                                    battleController.getSoldierUniqueId(), teamNo,
                                    posList==null?BattleUtils.getSoldierBornPos(battleController.getAstar().getAstarMap(), teamNo, cardConfig.getSoldier().initRange, 0, cardConfig.getSoldier().gridArea):posList.get(i),
                                    spriteTemp, cardConfig.soldierCount);

            addBattleSoldier(battleSoldierAObject);

            response.addSoldier(battleSoldierAObject.parseBattleUnit());

            sendList.add(battleSoldierAObject);

//            LogUtils.info("unique:" + battleSoldierAObject.getId() + " id:" + battleSoldierAObject.getSprite().id + " name:" + battleSoldierAObject.getName() + " position:" + battleSoldierAObject.getPosition());
        }

        LogUtils.info("出兵成功 -> " + response);

        battleController.dispatchMsg(SGMainProto.E_MSG_ID.MsgID_War_ToBattle_VALUE, response.build().toByteArray());

        nextPutCardTime = DataFactory.currentTime + BattleController.PUT_CARD_CD_TIME;
        LogUtils.debug("出兵时间 -> " + nextPutCardTime);

        for(BattleAObject battleAObject : sendList)
        {
            battleAObject.checkTypeSkill(ConstantFactory.SKILL_TYPE_BORN);
        }

        int targetSoldierSize = targetBattleTmp.getSoldierList().size();
        if(targetSoldierSize == 0)
        {
            BattleAObject targetMaster = targetBattleTmp.getMasterSoldier();
            for(BattleAObject battleAObject : sendList)
            {
                battleAObject.checkRoute(targetMaster);
            }
        }
    }



    public String getSpriteObjectIndex()
    {
        return null;
    }

    public boolean isMaxCrystal()
    {
        return curCrystal >= maxCrystal;
    }




    public void sendMsg(int code, byte[] data)
    {
        if(spriteController != null)
            spriteController.sendMsg(code, data);
    }


    /**
     * 获取战斗卡牌
     * @return
     */
    public CardDB getCardById(int id)
    {
        return cardMap.get(id);
    }

    /**
     * 上战场
     */
    public void toBattlefield(CardDB cardDB)
    {
        cardList.remove(cardDB);
        cardMap.remove(cardDB.id);
    }


    /**
     * 是否死亡
     * @return
     */
    public boolean isDie()
    {
        return masterSoldier.isDie();
    }

    public int getRouteSoldierCount(int route)
    {
        int count = 0;
        for(BattleAObject battleAObject : soldierList)
        {
            if(battleAObject.bornRoute == route)
                count++;
        }
        return count;
    }


    public boolean isHaveSoldier()
    {
        return cardList.size() > 0 || soldierList.size() > 0;
    }


    /**
     * 获取上一场这个士兵的历史数据
     * @param soldierId
     * @return
     */
    public SpriteTemp getSoldierHistoryTemp(int soldierId, int index)
    {
        if(battleTemp == null)
            return null;

        if(spriteController instanceof PlayerController)
            return battleTemp.getSpriteTemp(soldierId, SpriteTemp.IGNORE_INDEX);
        else
            return battleTemp.getSpriteTemp(soldierId, index);
    }



    public SGCommonProto.BattleResultCampWin getCampBattleWin()
    {
        SGCommonProto.BattleResultCampWin.Builder param = SGCommonProto.BattleResultCampWin.newBuilder();
        for(BattleAObject battleAObject : historySoldiers)
        {
            if(battleAObject.isInitObject() && battleAObject.getSpriteTemp() != null)
                param.addSoldier(SGCommonProto.CommonObject.newBuilder().setId(battleAObject.getConfigId()).setValue(battleAObject.getHPRate()));
        }
        for(CardDB cardDB : cardList)
        {
            param.addSoldier(SGCommonProto.CommonObject.newBuilder().setId(cardDB.id).setValue(100));
        }
        for(SpriteTemp temp : historyDeadSoldiers)
        {
            param.addSoldier(SGCommonProto.CommonObject.newBuilder().setId(temp.getId()).setValue(0));
        }
        LogUtils.info(spriteController.getName() + " 胜利方的剩余兵力 -> " + param.getSoldierList());
        return param.build();
    }

    public SGCommonProto.BattleResultCampLose getCampBattleLose(BattleResultParam resultParam)
    {
        SGCommonProto.BattleResultCampLose.Builder param = SGCommonProto.BattleResultCampLose.newBuilder();
        if(spriteController instanceof PlayerController)
        {
            CampBattleData campBattleData = ((PlayerController) spriteController).getPlayer().getCampBattleData();
            param.setDefeatTargetCount(campBattleData.curWinCount);
            param.setTotalExploit(campBattleData.curTotalExploit);
            param.setMaxContinueWin(campBattleData.curMaxContinueWin);
            int addExploitRate = campBattleData.curMaxContinueWin * 5;
            addExploitRate = addExploitRate < 0 ? 0 : addExploitRate;
            addExploitRate = addExploitRate > 100 ? 100 : addExploitRate;
            param.setAddExploitRate(addExploitRate);

            StableDataConfig stableData = DataFactory.getInstance().getGameObject(DataFactory.STABLE_DATA_KEY, E_StableDataType.CAMP_ACTIVITY_APPLY.getCode());
            GoodsData need = stableData.getGoodsData(campBattleData.applyCount);
            param.setApplyCharge(need.parse());

            if(resultParam != null && resultParam instanceof BattleResultParamCamp)
            {
                BattleResultParamCamp result = (BattleResultParamCamp) resultParam;

                if(result.getLoserBeforeReviveCount() == 0)
                    param.setReviveCount(-1);
                else
                    param.setReviveCount(result.getLoserAfterReviveCount());

                int camp = ((PlayerController) spriteController).getPlayer().camp;
                int i = 0;
                RankCamp rankCamp = null;
                StableDataConfig rewardStable = DataFactory.getInstance().getGameObject(DataFactory.STABLE_DATA_KEY, E_StableDataType.CAMP_ACTIVITY_REWARD.getCode());
                for(Object rank : result.getRankCampList())
                {
                    if(rank instanceof RankCamp)
                    {
                        rankCamp = (RankCamp) rank;
                        param.addRankCamp(SGCommonProto.CommonObject.newBuilder().setId(rankCamp.getCamp()).setValue(rankCamp.getValue()));
                        if(rankCamp.getCamp() == camp)
                        {
                            param.setCampRankAddRate(rewardStable.getCampActivityRankRewardPlus(i));
                        }
                    }
                    i++;
                }
            }
        }
        return param.build();
    }

    public void addBattleSoldier(BattleAObject battleAObject)
    {
        soldierList.add(battleAObject);
        historySoldiers.add(battleAObject);

        battleController.addSoldier(battleAObject);
    }

    public List<SGCommonProto.DamageObject> parseDamageList(int count)
    {
        List<SGCommonProto.DamageObject> list = new ArrayList<>();

        historySoldiers.sort(new Comparator<BattleAObject>() {
            @Override
            public int compare(BattleAObject o1, BattleAObject o2) {
                return new Long(o2.getDamage()).compareTo(o1.getDamage());
            }
        });
        for(BattleAObject battleAObject : historySoldiers)
        {
            if(list.size() >= count)
                break;

            if(!battleAObject.isInitObject())
                continue;

            list.add(battleAObject.parseDamage());
        }

        return list;
    }

    public long getTotalDamage()
    {
        long result = 0;
        for(BattleAObject battleAObject : historySoldiers)
        {
            result += battleAObject.getDamage();
        }
        return result + masterSoldier.getDamage();
    }



    public SGCommonProto.PlayerBaseInfo parseBaseInfo(String... names)
    {
        //子类实现
        return null;
    }


    public long getNextPutCardTime() {
        return nextPutCardTime;
    }


    public void removeSoldier(BattleAObject soldier)
    {
        soldierList.remove(soldier);
    }

    public void killEnemy()
    {
        killCount++;
    }

    public BattleController getBattleController() {
        return battleController;
    }

    public void setBattleController(BattleController battleController) {
        this.battleController = battleController;
    }

    public int getTeamNo() {
        return teamNo;
    }

    public SpriteController getSpriteController() {
        return spriteController;
    }

    public List<BattleAObject> getSoldierList() {
        return soldierList;
    }

    public boolean isReady() {
        return ready;
    }

    public void setReady(boolean ready) {
        this.ready = ready;
    }

    public int getCurCrystal() {
        return curCrystal;
    }

    public int getMaxCrystal() {
        return maxCrystal;
    }

    public SpriteBattleTmp getTargetBattleTmp() {
        return targetBattleTmp;
    }

    public void setTargetBattleTmp(SpriteBattleTmp targetBattleTmp) {
        this.targetBattleTmp = targetBattleTmp;
    }

    public BattleAObject getMasterSoldier() {
        return masterSoldier;
    }

    public List<CardDB> getCardList() {
        return cardList;
    }

    public boolean isAuto() {
        return isAuto;
    }

    public void setAuto(boolean isAuto) {
        this.isAuto = isAuto;
    }

    public List<CardDB> getHistoryCards() {
        return historyCards;
    }

    public Map<Integer, CrystalGrow> getCrystalGrowMap() {
        return crystalGrowMap;
    }

    public List<BattleAObject> getHistorySoldiers() {
        return historySoldiers;
    }

    public void setHistorySoldiers(List<BattleAObject> historySoldiers) {
        this.historySoldiers = historySoldiers;
    }

    public List<SpriteTemp> getHistoryDeadSoldiers() {
        return historyDeadSoldiers;
    }

    public void setHistoryDeadSoldiers(List<SpriteTemp> historyDeadSoldiers) {
        this.historyDeadSoldiers = historyDeadSoldiers;
    }

    public int getLv() {
        return lv;
    }

    class CrystalGrow
    {
        public int value;

        public boolean added;

        public CrystalGrow()
        {
            this.value = 1;
            this.added = false;
        }

        @Override
        public String toString() {
            return "{" +
                    "value=" + value +
                    '}';
        }
    }




    @Override
    public String toString() {
        return "{" +
                ", teamNo=" + teamNo +
                ", masterSoldier=" + masterSoldier +
                ", soldierList=" + soldierList +
                ", curCrystal=" + curCrystal +
                ", maxCrystal=" + maxCrystal +
                ", isAuto=" + isAuto +
                '}';
    }


}
